#!/usr/bin/env python
# -*- coding: utf-8 -*-
import SocketServer
import socket
import multiprocessing
import time
import requests
import json
import sys,os
import copy
import re
import codecs
from email.mime.text import MIMEText
from email.header import Header
import smtplib

dnspod_id = 35746
dnspod_token = '5f58f89275cd554ba62b6898ccfdced4'
verifyport = 8999
BACKLOG = 2**8
BUFFSIZE = 2**10
TIMESTAMP_FOMART = '%Y-%m-%d %H:%M:%S'
Nodes = []
#mail
_email_user='service@8z.net'
_email_pwd='mnJt47bZ'
_email_prov_host='smtp.exmail.qq.com'
_email_prov_port=465

class DNSPod(object):
    """
        DNSPodAPI接口类,单例
    """
    __instance = None
    def __new__(self,Id=0,Token='',*args,**kwargs):
        """
            Id和Token错误会返回空
        """
        self.id = Id
        self.token = Token
    
        self.http = requests.Session()
        self.http.verify = '/etc/pki/tls/cert.pem'
        self.base_params = {
            'format':'json',
            'lang':'cn',
            'login_token':'%s,%s' % (self.id,self.token)
        }
        self.baseurl = 'https://dnsapi.cn'
        verify = False
        verifyurl = self.baseurl + '/Info.Version'
        try:
            res = self.http.post(url=verifyurl,data=self.base_params)
            result = json.loads(res.text)
            verify = result['status']['code'] == "1"
        except requests.exceptions as e:
            raise(e)
        except (ValueError,KeyError):
            pass
        if verify:
            if not DNSPod.__instance:
                DNSPod.__instance = object.__new__(self,Id,Token,*args,**kwargs)
            return DNSPod.__instance
        else:
            print(u'验证失败,%s' % result['status']['message'])
            return None
        
    def __init__(self,Id=0,Token=''):
        if self == None:
            return
        self.public_ret_reason = {
            '-1':u'登录失败',
            '-2':u'API使用超出限制',
            '-3':u'不是合法代理(仅用于代理接口)',
            '-4':u'不在代理名下(仅用于代理接口)',
            '-7':u'无权使用此接口',
            '-8':u'登录失败次数过多，帐号被暂时封禁',
            '85':u'帐号异地登录，请求被拒绝',
            '-99':u'此功能暂停开放，请稍候重试',
            '1':u'操作成功',
            '2':u'只允许POST方法',
            '3':u'未知错误',
            '6':u'用户ID错误 (仅用于代理接口)',
            '7':u'用户不在您名下 (仅用于代理接口)',
            '83':u'该帐户已经被锁定，无法进行任何操作',
            '85':u'该帐户开启了登录区域保护，当前IP不在允许的区域内'
        }

    def __verify(self):
        url = self.baseurl + '/Info.Version'
        try:
            res = self.http.post(url=url,params=self.base_params)
            result = json.loads(res.text)
        except requests.exceptions as e:
            raise(e)
        except ValueError:
            return False
        return result['status']['code'] == '1'

    def RecordModify(self,domain,sub_domain,record_id,record_type,record_line,value,status='disable'):
        private_ret_reason = {
            '-15':u'域名已被封禁',
            '-7':u'企业账号的域名需要升级才能设置',
            '-8':u'代理名下用户的域名需要升级才能设置',
            '6':u'域名ID错误',
            '7':u'不是域名所有者或没有权限',
            '8':u'记录ID错误',
            '21':u'域名被锁定',
            '22':u'子域名不合法',
            '23':u'子域名级数超出限制',
            '24':u'泛解析子域名错误',
            '500025':u'A记录负载均衡超出限制',
            '500026':u'CNAME记录负载均衡超出限制',
            '26':u'记录线路错误',
            '27':u'记录类型错误',
            '29':u'TTL',
            '30':u'MX',
            '31':u'URL记录数超出限制',
            '32':u'NS',
            '33':u'AAAA',
            '34':u'记录值非法',
            '35':u'添加的IP不允许',
            '36':u'@主机的NS纪录只能添加默认线路',
            '82':u'不能添加黑名单中的IP'
        }
        url = self.baseurl + '/Record.Modify'
        params = {
            'domain':domain,
            'record_id':record_id,
            'sub_domain':sub_domain,
            'record_type':record_type,
            'record_line':record_line,
            'value':value,
            'status':status
        }
        params.update(self.base_params)
        res = self.http.post(url=url,data=params)
        try:
            ret = json.loads(res.text)['status']['code']
            try:
                print(
                    'RecordModify -> %s.%s[%s] = %s %s %s' %\
                    (sub_domain,domain,record_line,value,status,private_ret_reason[ret])
                )
            except KeyError:
                print(private_ret_reason[ret])
            finally:
                return ret == "1"
        except ValueError:
            return False

    def RecordCreate(self,domain,sub_domain,record_type,record_line,value,status='disable'):
        private_ret_reason = {
            '-15':u'域名已被封禁',
            '-7':u'企业账号的域名需要升级才能设置',
            '-8':u'代理名下用户的域名需要升级才能设置',
            '6':u'缺少参数或者参数错误',
            '7':u'不是域名所有者或者没有权限',
            '21':u'域名被锁定',
            '22':u'子域名不合法',
            '23':u'子域名级数超出限制',
            '24':u'泛解析子域名错误',
            '500025':u'A记录负载均衡超出限制',
            '500026':u'CNAME记录负载均衡超出限制',
            '26':u'记录线路错误',
            '27':u'记录类型错误',
            '30':u'MX',
            '31':u'存在冲突的记录(A记录、CNAME记录、URL记录不能共存)',
            '32':u'记录的TTL值超出了限制',
            '33':u'AAAA',
            '34':u'记录值非法',
            '36':u'@主机的NS纪录只能添加默认线路',
            '82':u'不能添加黑名单中的IP'
        }
        url = self.baseurl + '/Record.Create'
        params = {
            'domain':domain,
            'sub_domain':sub_domain,
            'record_type':record_type,
            'record_line':record_line,
            'value':value,
            'status':status
        }
        params.update(self.base_params)
        res = self.http.post(url=url,data=params)
        try:
            ret = json.loads(res.text)['status']['code']
            try:
                print(
                    'RecordCreate -> %s.%s[%s] = %s %s %s' %\
                    (sub_domain,domain,record_line,value,status,self.public_ret_reason[ret])
                    )
            except KeyError:
                print(private_ret_reason[ret])
            finally:
                return ret == "1"
        except ValueError:
            return False

    def RecordRemove(self,domain,record_id):
        private_ret_season = {
            '-15':u'域名已被封禁',
            '-7':u'企业账号的域名需要升级才能设置',
            '-8':u'代理名下用户的域名需要升级才能设置',
            '6':u'域名ID错误',
            '7':u'不是域名所有者或没有权限',
            '8':u'记录ID错误',
            '21':u'域名被锁定'
        }
        url = self.baseurl + '/Record.Remove'
        params = {
            'domain':domain,
            'record_id':record_id
        }
        params.update(self.base_params)
        res = self.http.post(url=url,data=params)
        try:
            ret = json.loads(res.text)['status']['code']
            try:
                print(
                    'RecordModify -> %s - id:%s %s' %\
                    (domain,record_id,self.public_ret_reason[ret])
                )
            except KeyError:
                print(private_ret_season[ret])
            finally:
                return ret == "1"
        except ValueError:
            return False

    def RecordList(self,domain,**kwargs):
        """
            keyword
            sub_domain
            offset
            length
        """
        private_ret_season = {
            '-7':u'企业账号的域名需要升级才能设置',
            '-8':u'代理名下用户的域名需要升级才能设置',
            '6':u'域名ID错误',
            '7':u'记录开始的偏移无效',
            '8':u'共要获取的记录的数量无效',
            '9':u'不是域名所有者',
            '10':u'没有记录'
        }
        url = self.baseurl + '/Record.List'
        params = {
            'domain':domain,
        }
        for i in kwargs:
            if i == 'keyword':
                params['keyword'] = kwargs['keyword']
            elif i == 'sub_domain':
                 params['sub_domain'] = kwargs['sub_domain']
            elif i == 'offset':
                 params['offset'] = kwargs['offset']
            elif i == 'length':
                 params['length'] = kwargs['length']
            elif i == 'offset':
                 params['offset'] = kwargs['offset']
        params.update(self.base_params)
        res = self.http.post(url=url,data=params)
        try:
            return json.loads(res.text)
        except:
            return None
    
    def RecordInfo(self,domain,record_id):
        private_ret_season = {
            '-15':u'域名已被封禁',
            '-7':u'企业账号的域名需要升级才能设置',
            '-8':u'代理名下用户的域名需要升级才能设置',
            '6':u'域名ID错误',
            '7':u'不是域名所有者或没有权限',
            '8':u'记录ID错误'
        }
        url = self.baseurl + '/Record.Info'
        params = {
            'domain':domain,
            'record_id':record_id
        }
        params.update(self.base_params)
        res = self.http.post(url=url,data=params)
        try:
            return json.loads(res.text)
        except ValueError:
            return None

    def RecordStatus(self,domain,record_id,status):
        private_ret_season = {
            '-15':u'域名已被封禁',
            '-7':u'企业账号的域名需要升级才能设置',
            '-8':u'代理名下用户的域名需要升级才能设置',
            '6':u'域名ID错误',
            '7':u'不是域名所有者或没有权限',
            '8':u'记录ID错误',
            '21':u'域名被锁定'
        }
        url = self.baseurl + '/Record.Status'
        params = {
            'domain':domain,
            'record_id':record_id,
            'status':status
        }
        params.update(self.base_params)
        res = self.http.post(url=url,data=params)
        try:
            ret = json.loads(res.text)['status']['code']
            try:
                print(
                    '%s - %s %s %s' %\
                    (domain,record_id,status,self.public_ret_reason[ret])
                )
            except KeyError:
                print(private_ret_season[ret])
            finally:
                return ret == "1"
        except ValueError:
            return False

class TcpServer(object):
    BACKLOG = 2**8
    BUFFSIZE = 2**10
    def __init__(self,addr):
        self.addr = addr
        self.socketserver = None
    def run(self):
        queue = self.__queue = multiprocessing.Queue()
        lock = self.__lock = multiprocessing.Lock()
        class Server(SocketServer.BaseRequestHandler):
            def handle(self):
                lock.acquire()
                try:
                    data = self.request.recv(TcpServer.BUFFSIZE)
                    queue.put([time.time(),data])
                except:
                    return
                finally:
                    lock.release()
        SocketServer.ThreadingTCPServer.allow_reuse_address = True
        SocketServer.ThreadingTCPServer.request_queue_size = BACKLOG
        self.socketserver = SocketServer.ThreadingTCPServer(self.addr,Server)
        self.Server = multiprocessing.Process(target=self.socketserver.serve_forever,args=())
        self.Server.start()

    def getdata(self):
        data = None
        if self.__queue.qsize() > 0:
            self.__lock.acquire()
            data = self.__queue.get()
            self.__lock.release()
        return data

    def getqueue(self):
        return self.__queue

    def flushqueue(self):
        self.__lock.acquire()
        while self.__queue.qsize() > 0:
            self.__queue.get()
        self.__lock.release()

    def __del__(self):
        self.server.shutdown()
        self.Server.join()

class Node(object):
    __CheckLock = multiprocessing.Lock()
    __node = 0
    def __init__(self,dnsapi,tcpserver,value,addrs,name,desc=''):
        self.desc = desc
        self.value = value
        self.name = name 
        self.logfile = './%s.log' % self.name
        self.dnsapi = dnsapi
        self.tcpserver = tcpserver
        self.addrs = addrs
        self.domain = re.search("\.([a-z0-9]+\.[a-z]+)$",self.value).group(1)
        self.sub_domain = self.value[:self.value.find('.' + self.domain)]
        Node.__node += 1
        self.LimitMaxTimeout = 60   #最大故障时间(秒)
        self.LimitMaxLossRate = 0.2 #最大丢包率
        self.live  = None           #循环检查进程
        self.MaxLogTimes = 300      #检测循环记录一次数据
        self.__ActiveSuccess = multiprocessing.Value('i',0) #检测成功次数
        self.__ActiveCount = multiprocessing.Value('i',0)   #检测次数
        self.__ActiveLoss = multiprocessing.Value('i',0)    #检测失败次数
        self.ActiveInterval = 6                             #检测间隔时间
        self.__Active = multiprocessing.Value('b',False)    #是否在循环
        self.__Time = multiprocessing.Value('f',0.0)        #连接延迟
        self.__ConnectRate = multiprocessing.Value('f',0.0) #连通率
        self.__LossRate = multiprocessing.Value('f',0.0)    #丢包率
        self.__NodeValid = multiprocessing.Value('b',False) #可用性
        with codecs.open(self.logfile,'a','utf-8') as pf:
            pf.write('\n%s\n' % (time.strftime(TIMESTAMP_FOMART)))
            pf.write(
                'name:%s\ndesc:%s\naddress:\n' %(self.name,self.desc)
                )
            for i in self.addrs:
                pf.write('\t%s->%s\n' % (i,self.addrs[i]))
        Nodes.append(self)
        self.Sync()
        self.ActiveDaemon(IsProxyServer())
    def Telnet(self):
        result = []
        for line in self.addrs:
            addr = self.addrs[line]
            s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            s.settimeout(3)
            data = str(time.time())
            try:
                s.connect((addr,verifyport))
                s.sendall(data)
                s.recv(BUFFSIZE)
            except:
                return []
            finally:
                s.close()
            result.append(data)
        return result
    def Check(self):
        result = [False,0.0]
        #print('%s at Check ' % self.name)
        Node.__CheckLock.acquire()
        self.tcpserver.flushqueue()
        data = self.Telnet()
        #print'Telnet return %s' % data
        timeout = 0.0
        if not data:
            result[0] = False
        else:
            for i in data:
                recv = self.tcpserver.getdata()
                #print '%s,%s' % (recv[0],recv[1])
                try:
                    if i == recv[1].strip():
                        timeout += recv[0] - float(recv[1])
                    else:
                        result[0] = False
                        break
                except:
                    result[0] = False
                    break
            else:
                result[1] = timeout / len(data)
                result[0] = True
        Node.__CheckLock.release()
        #print('%s Check end' % self.name)
        return result
    @staticmethod
    def slovediff(array):
        first = array[0]
        result = 0.0
        for i in array[1:]:
            result += i - first
            first = i
        return result

    def ActiveCheck(self):
        self.__ActiveCount.value = 0
        self.__ActiveSuccess.value = 0
        self.__ActiveLoss.value = 0
        error = 0
        loss = []
        __ActiveLoss = 0
        times = int(self.LimitMaxTimeout / self.ActiveInterval)   #最大故障时间的次数
        self.__LossRate.value = 0.0
        self.__ConnectRate.value = 0.0
        logstamploss = 0
        TimeLazy = 60
        timesum = 0
        Lazy = {'invalid':0,'loss':0}
        while self.__Active.value:
            start = time.time()
            end = start + self.ActiveInterval
            r,t = self.Check()
            if r:
                self.__ActiveCount.value += 1
                self.__ActiveSuccess.value += 1
                timesum += t
                self.__Time.value = timesum / self.__ActiveSuccess.value
                self.__ConnectRate.value = float(self.__ActiveSuccess.value) / self.__ActiveCount.value
                if not self.__NodeValid.value and self.__ActiveSuccess.value >= times and self.__ConnectRate.value > 0.8:  #故障恢复
                        data = u'节点恢复'
                        self._LogActive()
                        self.log(data,0)
                        notice(u'%s %s' % (self.desc,data),0)
                        Lazy['invalid'] = 0
                        self.__NodeValid.value = True
            else:
                self.__ActiveLoss.value += 1
                self.__ActiveCount.value += 1
                self.__ConnectRate.value = float(self.__ActiveSuccess.value) / self.__ActiveCount.value
                loss.append(time.time())
                if self.__ActiveLoss.value >= times:    #出现故障
                    #import pdb
                    #pdb.Pdb(stdin=open('p_in','r+'), stdout=open('p_out','w+')).set_trace()
                    self.__LossRate.value = self.ActiveInterval/(self.slovediff(loss)/(self.__ActiveLoss.value-1))
                    if self.__LossRate.value > self.LimitMaxLossRate:   #严重丢包
                        end = start + TimeLazy
                        data = u'节点失效，丢包率 %s ,%s 后重新开始检测' % (self.__LossRate.value,time.strftime('%H:%M:%S',time.localtime(end)))
                        if self.__NodeValid.value == True:
                            Lazy['invalid'] = notice('%s %s' % (self.desc,data),Lazy['invalid'],10800)  #三个小时不重复发送
                        self._LogActive()
                        self.log(data,0)
                        self.__NodeValid.value = False
                        time.sleep(end-time.time())
                        self._ResetActive()
                        timesum = 0.0
                        del loss
                        loss = []
                        continue
                    else:                                               #有丢包
                        data = u'%s 丢包率为 %s' % (self.desc,self.__LossRate.value)
                        logstamploss = self.log(data,logstamp_loss,600)
                        Lazy['loss'] = notice(data,Lazy['loss'],3600)   #一个小时不重复发送
                        continue
            if self.__ActiveCount.value >= self.MaxLogTimes:
                self._LogActive()
                self._ResetActive()
                timesum = 0.0
                del loss
                loss = []
            if time.time() < end:
                time.sleep(end - time.time())
        self.__NodeValid.value = False

    def _ResetActive(self):
        self.__ActiveSuccess.value = 0
        self.__ActiveCount.value = 0
        self.__ActiveLoss.value = 0
        self.__Time.value = 0.0
        self.__ConnectRate.value = 0.0
        self.__LossRate.value = 0.0
    def _LogActive(self):
        with codecs.open(self.logfile,'a','utf-8') as pf:
            pf.write(time.strftime(TIMESTAMP_FOMART))
            pf.write('==>Count:%s,Success:%s,,Loss:%s,Time:%s,ConnectRate:%s,LossRate:%s\n' % 
                    (self.__ActiveCount.value,
                    self.__ActiveSuccess.value,
                    self.__ActiveLoss.value,
                    str(self.__Time.value)[:5],
                    self.__ConnectRate.value,
                    self.__LossRate.value)
                )
    def ActiveDaemon(self,status=False):
        self.__Active.value = status
        if self.__Active.value:
            if self.live == None:
                self.live = multiprocessing.Process(target=self.ActiveCheck,args=())
                self.__NodeValid.value = True
                self.live.start()
            else:
                if not self.live.is_alive():
                    del self.live
                    if self.__Active.value == True:
                        self.live = multiprocessing.Process(target=self.ActiveCheck,args=())
                        self.__NodeValid.value = True
                        self.live.start()
                return True
        else:
            if self.live:
                self.live.join()
                del self.live
                self.live = None
            return False
    def ActiveStatus(self):
        return {
            'Active':self.__Active.value,
            'Count':self.__ActiveCount.value,
            'Success':self.__ActiveSuccess.value,
            'Loss':self.__ActiveLoss.value,
            'ConnectRate':self.__ConnectRate.value,
            'LossRate':self.__LossRate.value,
            'Time':self.__Time.value
        }
    def IsValid(self):
        return bool(self.__NodeValid.value)
    def IsActive(self):
        return bool(self.__Active.value)
    def SetActive(self,status):
        if type(status) is bool:
            self.__Active.value = status
            return status
    def GetActiveSuccess(self):
        return self.__ActiveSuccess.value
    def GetActiveCount(self):
        return self.__ActiveCount.value
    def GetActiveLoss(self):
        return self.__ActiveLoss.value
    def GetConnectRate(self):
        return self.__ConnectRate.value
    def GetLossRate(self):
        return self.__LossRate.value
    def GetConnectTime(self):
        return self.__Time.value
    def __str__(self):
        return self.name
    def BindProxy(self,addr):
        domain = re.search("\.([a-z0-9]+\.[a-z]+)$",addr).group(1)
        sub_domain = addr[:addr.find('.' + domain)]
        Records = self.dnsapi.RecordList(domain,sub_domain=sub_domain)
        if Records['status']['code'] == '10':
            #创建DNS记录
            return self.dnsapi.RecordCreate(
                domain=domain,
                sub_domain=sub_domain,
                record_type='CNAME',
                record_line=u'默认',
                value=self.value,
                status='enable'
                )
        elif Records['status']['code'] == '1':
            count = len(Records['records'])
            if count == 1:
                record_id = Records['records'][0]['id']
                return self.dnsapi.RecordModify(
                    domain=domain,
                    sub_domain=sub_domain,
                    record_id=record_id,
                    record_type='CNAME',
                    record_line=u'默认',
                    value=self.value,
                    status = 'enable'
                    )
            else:
                for record in Records['records']:
                    record_id = record['id']
                    self.dnsapi.RecordRemove(domain,record_id)
                return self.dnsapi.RecordCreate(
                    domain=domain,
                    sub_domain=sub_domain,
                    record_type='CNAME',
                    record_line=u'默认',
                    value=self.value,
                    status='enable'
                    )
        else:
            return False
    def Sync(self):
        addrs = copy.deepcopy(self.addrs)
        records = self.dnsapi.RecordList(domain=self.domain,sub_domain=self.sub_domain)
        if records['status']['code'] == '1':
            for record in records['records']:
                if record['status'] == 'disable':
                    #删除记录
                    self.dnsapi.RecordRemove(self.domain,record['id'])
                else:
                    if addrs.has_key(record['line']):
                        if addrs[record['line']] == record['value']:
                            del addrs[record['line']]
                            continue
                        else:
                            #修改记录
                            self.dnsapi.RecordModify(
                                domain=self.domain,
                                sub_domain=self.sub_domain,
                                record_id=record['id'],
                                record_type='A',
                                record_line=record['line'],
                                value=addrs[record['line']],
                                status='enable'
                                )
                            del addrs[record['line']]
                    else:
                        #删除记录
                        self.dnsapi.RecordRemove(self.domain,record['id'])
            pass
        elif records['status']['code'] != "10":
            return False
        #提交没有记录的记录
        for line in addrs:
            #添加记录
            self.dnsapi.RecordCreate(domain=self.domain,
                sub_domain=self.sub_domain,
                record_type='A',
                record_line=line,
                value=addrs[line],
                status='enable')
        return True
    def log(self,data,timestamps='',delay=1200):
        now = time.time()
        if not timestamps or now - timestamps > delay:
            strtime = time.strftime(TIMESTAMP_FOMART)
            with codecs.open(self.logfile,'a','utf-8') as pf:
                pf.write('%s :%s\n'%(strtime,data))
            print('%s:%s => %s'%(self.name,strtime,data))
        else:
            return time.time() if not timestamps or now - timestamps > delay else timestamps
def GetProxyNode(api,addr,NodeSet):
    domain = re.search("\.([a-z0-9]+\.[a-z]+)$",addr).group(1)
    sub_domain = addr[:addr.find('.' + domain)]
    Records = api.RecordList(domain,sub_domain=sub_domain)
    if Records['status']['code'] == '1':
        records = Records['records']
        if len(records) == 1:
            record = records[0]
            if record['type'] == 'CNAME' and record['line'] == u'默认':
                for node in NodeSet:
                    if record['value'] == node.value + '.':
                        return node
    return None
def GetSuitableNode():
    GoodConnectRate = 0.93
    Time = 100.0
    Connect = 0.0
    SuitableNode = None
    for node in Nodes:
        if node.IsActive() and node.IsValid():
            nodetime = node.GetConnectTime()
            noderate = node.GetConnectRate()
            if SuitableNode:
                if nodetime < Time and (noderate > GoodConnectRate or noderate < Connect):
                    Time = nodetime
                    Connect = noderate
                    SuitableNode = node
            else:
                if nodetime < Time and noderate > Connect:
                    Time = nodetime
                    Connect = noderate
                    SuitableNode = node
    else:
        if not SuitableNode:
            notice(u'没有一个可用节点',0)
        return SuitableNode

email_sender = _email_user
email_pass = _email_pwd
admin='weskiller@vip.qq.com'
def notice(data,timestamps,delay=1200):
    now = time.time()
    if timestamps or now - timestamps > delay:
        if not IsProxyServer():
            return now
        msg = MIMEText(data,'plain','utf-8')
        msg['Subject'] = Header(u'高防脚本警告','utf-8')
        msg['From'] = 'auto_switch'
        msg['to'] = admin
        try:
            smail = smtplib.SMTP_SSL(_email_prov_host,_email_prov_port)
            smail.login(email_sender,email_pass)
            smail.sendmail(email_sender,admin,msg.as_string())
            smail.quit()
        except smtplib.SMTPException as e:
            print(e)
        finally:
            return now
    else:
        return timestamps
def IsProxyServer():
    return os.system(shellcommand) == 0

ProxyDomain='img.8z.net'
ProxyIPAddress='121.201.48.227'
shellcommand = 'ip address show dev eth0|grep -Pq "%s"' % ProxyIPAddress

def main():
    dnsapi = DNSPod(dnspod_id,dnspod_token)
    if not dnsapi:
            print(u'dnspod登录失败，退出')
            sys.exit(-1)
    Server = TcpServer(('0.0.0.0',verifyport))
    Server.run()   
    nodell = Node(dnsapi,Server,
                value='img.ll.8z.net',
                addrs={u'默认':'116.211.145.100'},
                name='ll',
                desc=u'乐乐网络-湖北武汉')
    node360 = Node(dnsapi,Server,
                value='img.360.8z.net',
                addrs={u'默认':'183.60.107.34',u'联通':'119.63.39.34'},
                name='360',
                desc=u'360集群-广东佛山')
    #nodealiyun = Node(dnsapi,Server,
    #            value='img.aliyun.8z.net',
    #            addrs={u'默认':'118.178.214.165',u'电信':'116.211.172.52',u'联通':'119.63.39.34'},
    #            name='aliyun',
    #            desc=u'阿里云高防')
    ProxyNode = GetProxyNode(dnsapi,ProxyDomain,Nodes)
    noticed = {
        'BindError':600,
        'ProxyInvaild':600
    }
    if ProxyNode:
        ProxyNode.log(u'代理域名 %s 绑定在本节点' % ProxyDomain)
    PreProxy = True
    while True:
        ProxyServer = IsProxyServer()
        if ProxyServer:
            for node in Nodes:
                if not node.IsActive():
                    node.ActiveDaemon(True)
            if (ProxyNode and ProxyNode.IsValid()):
                pass
            else:
                NewNode = GetSuitableNode()
                if NewNode:
                    if NewNode.BindProxy(ProxyDomain):
                        NewNode.log(u'绑定代理域名 %s 成功' % ProxyDomain)
                        if ProxyNode:
                            ProxyNode.log(u'代理域名 %s 从本节点转移到 %s' % (ProxyDomain,NewNode.name))
                        notice(u'代理域名 %s 从 %s 节点转移到 %s ' % (ProxyDomain,ProxyNode.desc,NewNode.desc),0)
                        ProxyNode = NewNode
                    else:
                        NewNode.log(u'绑定代理域名 %s 失败' % ProxyDomain)
                        noticed['BindError'] = notice('%s 节点绑定代理域名 %s 失败' % (NewNode.name,ProxyDomain),noticed['BindError'],600)
                        print('%s 节点绑定代理域名 %s 失败' % (NewNode.name,ProxyDomain))
                        if ProxyNode:
                            ProxyNode.log(u'代理域名 %s 未能从本节点转移到 %s' % (ProxyDomain,NewNode.name))
                        else:
                            notice('代理域名 %s 未绑定任何节点' % ProxyDomain,0)
                            print('代理域名 %s 未绑定任何节点' % ProxyDomain,0)
                else:
                    ProxyNode.log(u'当前代理节点 %s 出现问题，没有其他的可用节点' % ProxyNode.name)
                    noticed['ProxyInvaild'] = notice('当前代理节点 %s 出现问题，没有其他的可用节点'% ProxyNode.name,noticed['ProxyIsUnvaild'],600)
                    print('当前代理节点 %s 出现问题，没有其他的可用节点'% ProxyNode.name)
        else:
            for node in Nodes:
                if node.IsActive():
                    node.ActiveDaemon(False)
            if PreProxy == True:
                print('本机没有域名 %s 的代理地址 %s' % (ProxyDomain,ProxyIPAddress))
                PreProxy = False
        time.sleep(60)
    for node in Nodes:
        node.ActiveDaemon(False)
    Server.__del__()
if __name__ == '__main__':
    main()